namespace SimpleWebServices.Web.Mvc
{
    using System;
    using System.IO;
    using System.Web;
    using System.Web.Mvc;
    using Moq;
    using SimpleWebServices.IO;
    using Xunit;

    public sealed class ContentMD5AttributeFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<ContentMD5Attribute>()
                .DerivesFrom<ActionFilterAttribute>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .IsDecoratedWith<AttributeUsageAttribute>()
                .Result);
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new ContentMD5Attribute());
        }

        [Fact]
        public void op_OnActionExecuting_FilterExecutedContextNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ContentMD5Attribute().OnActionExecuting(null));
        }

        [Fact]
        public void op_OnActionExecuting_FilterExecutedContext()
        {
            var mock = new Mock<HttpContextBase>();
            mock.SetupSet(x => x.Response.BufferOutput).Callback(expected => Assert.True(expected)).Verifiable();
            mock.SetupSet(x => x.Response.Filter).Callback(expected => Assert.IsType<WrappedStream>(expected)).Verifiable();

            using (MemoryStream stream = new MemoryStream())
            {
                mock.SetupGet<Stream>(x => x.Response.Filter).Returns(stream).Verifiable();

                new ContentMD5Attribute().OnActionExecuting(new ActionExecutingContext() { HttpContext = mock.Object });
            }

            mock.VerifyAll();
        }

        [Fact]
        public void op_OnActionExecuted_FilterExecutedContextNull()
        {
            Assert.Throws<ArgumentNullException>(() => new ContentMD5Attribute().OnActionExecuted(null));
        }

        [Fact]
        public void op_OnActionExecuted_FilterExecutedContext()
        {
            var mock = new Mock<HttpContextBase>();
            mock.Setup(x => x.Response.AppendHeader(It.IsAny<string>(), It.IsAny<string>())).Verifiable();

            using (MemoryStream stream = new MemoryStream())
            {
                mock.SetupGet<Stream>(x => x.Response.Filter).Returns(new WrappedStream(stream)).Verifiable();

                new ContentMD5Attribute().OnActionExecuted(new ActionExecutedContext() { HttpContext = mock.Object });
            }

            mock.VerifyAll();
        }
    }
}